//
// Created by work on 24-6-6.
//

#ifndef IOT_PLAT_CRTDEVICEINFO_H
#define IOT_PLAT_CRTDEVICEINFO_H

#include <string>
#include <utility>
#include <jsoncpp/json/json.h>
#include <os/miscellany/date_time.h>
#include <os/miscellany/CValue.h>
#include <unordered_map>
#include <os/miscellany/stddef.h>

namespace iotplat {

    class CRtDeviceInfo {
    public:
        enum ECause{
            ETest,
            ECollect,
            EDemonstration
        };

        enum EDeviceCol {
            EUser = 0x00,
            EName,
            EModelName,
            EDescr,
            ESn,
            EGroupIngs,
            EConfigs,
            ELocation,
            ECreate_time,
            EProtocol,
            EFirmwareVersion,
            ELastOnlineTime,
            EAccruedOnlineTime,
            ESpecifications,
            EValid,

            EPulse,
            ELoginTime,
            EOnlineState
        };

        std::string user;
        std::string name;
        std::string model_name;
        std::string descr;
        int sn;
        std::string grouping;
        Json::Value configs;
        std::string location;
        CDateTime create_time;
        std::string protocol;
        std::string firmware_version;
        CDateTime last_online_time;
        int accrued_online_time;
        std::string specifications;
        bool valid;

        int pulse;
        CDateTime login_time;
        bool online_state;

        static std::map<CRtDeviceInfo::EDeviceCol, std::string> rtDeviceColToStringMap;

        Json::Value toJson();

        void fromJson(Json::Value json);

    public:
        explicit CRtDeviceInfo();

    private:
    };

    static const std::string t_device_name = "t_iot_device";
#define DEVICE_ENUM                  CRtDeviceInfo::EDeviceCol
#define deviceFieldName(type)        CRtDeviceInfo::rtDeviceColToStringMap.find(type)->second

    struct SRtDeviceYxInfo {
        int v = 0;
        CDateTime ts;
        CRtDeviceInfo::ECause cause = CRtDeviceInfo::ECollect;

        SRtDeviceYxInfo() = default;
        SRtDeviceYxInfo(int pv, CDateTime pts, CRtDeviceInfo::ECause pcause) {
            v = pv;
            ts = pts;
            cause = pcause;
        }
        Json::Value toJson() {
            Json::Value json;
            json["v"] = v;
            json["ts"] = ts.ToString();
            json["cause"] = (int)cause;
            return json;
        }
        std::unordered_map<std::string, std::string> toUnorderedMap() const {
            std::unordered_map<std::string, std::string> result;
            result["v"] = std::to_string(v);
            result["ts"] = ts.ToString();
            result["cause"] = std::to_string((int)cause);
            return result;
        }
    };

    struct SRtDeviceYcInfo {
        float v = 0;
        CDateTime ts;
        int alarm_count = 0;
        CRtDeviceInfo::ECause cause = CRtDeviceInfo::ECollect;
        bool alarm = false;
        CDateTime limit_time;

        SRtDeviceYcInfo() = default;
        SRtDeviceYcInfo(float pv, CDateTime pts, int palarm_count, CRtDeviceInfo::ECause pcause, bool palarm, CDateTime plimit_time) {
            v = pv;
            ts = pts;
            alarm_count = palarm_count;
            cause = pcause;
            alarm = palarm;
            limit_time = plimit_time;
        }
        Json::Value toJson() {
            Json::Value json;
            json["v"] = v;
            json["ts"] = ts.ToString();
            json["alarm_count"] = alarm_count;
            json["cause"] = (int)cause;
            json["alarm"] = alarm;
            json["limit_time"] = limit_time.ToString();
            return json;
        }

        std::unordered_map<std::string, std::string> toUnorderedMap() const {
            std::unordered_map<std::string, std::string> result;
            result["v"] = std::to_string(v);
            result["ts"] = ts.ToString();
            result["cause"] = std::to_string((int)cause);
            result["alarm_count"] = std::to_string(alarm_count);
            result["alarm"] = BOOL_TO_STRING(alarm);
            result["limit_time"] = limit_time.ToString();
            return result;
        }
    };

    struct SRtDeviceYkInfo {
        int v = 0;
        CDateTime ts;
        CRtDeviceInfo::ECause cause = CRtDeviceInfo::ECollect;
        SRtDeviceYkInfo() = default;
        SRtDeviceYkInfo(int pv, CDateTime pts, CRtDeviceInfo::ECause pcause) {
            v = pv;
            ts = pts;
            cause = pcause;
        }
        Json::Value toJson() {
            Json::Value json;
            json["v"] = v;
            json["ts"] = ts.ToString();
            json["cause"] = (int)cause;
            return json;
        }
        std::unordered_map<std::string, std::string> toUnorderedMap() const {
            std::unordered_map<std::string, std::string> result;
            result["v"] = std::to_string(v);
            result["ts"] = ts.ToString();
            result["cause"] = std::to_string((int)cause);
            return result;
        }
    };

    struct SRtDeviceParameterInfo {
        CValue v;
        CDateTime ts;
        CRtDeviceInfo::ECause cause = CRtDeviceInfo::ECollect;

        SRtDeviceParameterInfo() = default;
        SRtDeviceParameterInfo(CValue pv, CDateTime pts, CRtDeviceInfo::ECause pcause) {
            v = std::move(pv);
            ts = pts;
            cause = pcause;
        }
        Json::Value toJson() {
            Json::Value json;

            switch (v.type()) {
                case CValue::IOT_Int:
                    json["v"] = v.asInt();
                    break;
                case CValue::IOT_String:
                    json["v"] = v.asString();
                    break;
                case CValue::IOT_DateTime:
                    json["v"] = v.asDateTime().ToString();
                    break;
                default:
                    json["v"] = "0";
                    break;
            }

            json["ts"] = ts.ToString();
            json["cause"] = (int)cause;
            return json;
        }
        std::unordered_map<std::string, std::string> toUnorderedMap() {
            std::unordered_map<std::string, std::string> result;
            switch (v.type()) {
                case CValue::IOT_Int:
                    result["v"] =  std::to_string(v.asInt());
                break;
                case CValue::IOT_String:
                    result["v"] = v.asString();
                break;
                case CValue::IOT_DateTime:
                    result["v"] = v.asDateTime().ToString();
                break;
                default:
                    result["v"] = "0";
                break;
            }
            result["ts"] = ts.ToString();
            result["cause"] = std::to_string((int)cause);
            return result;
        }
    };
} // iotplat

#endif //IOT_PLAT_CRTDEVICEINFO_H
